package com.jianganming.nio.chat;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

public class ChatServer {
    private ServerSocketChannel serverSocketChannel;
    private Selector selector;

    public ChatServer(){
        try {
            serverSocketChannel = ServerSocketChannel.open();

            serverSocketChannel.socket().bind(new InetSocketAddress(9999));
            //设置为非阻塞
            serverSocketChannel.configureBlocking(false);

            selector = Selector.open();
            //注册到selector
            serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT);
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    public void listen()throws Exception{
        while (true){
            //服务器等待了1秒,如果没有客户端连接就轮训，直到客户端连接成功
            if(selector.select()>0){
                //获取选择器的key
                Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();

                while (iterator.hasNext()){

                    SelectionKey key = iterator.next();
                    //如果获得连接
                    if(key.isAcceptable()){
                        //注册
                        registerSocketChannel();
                    }
                    //如果是可读状态
                    if(key.isReadable()){
                        //读取数据
                        readData(key);
                    }

                    iterator.remove();
                }
            }else {
                System.out.println("等待...");
            }


        }
    }

    private void registerSocketChannel()throws Exception {
        SocketChannel socketChannel = serverSocketChannel.accept();

        socketChannel.configureBlocking(false);
        //注册为可读的通道
        socketChannel.register(selector,SelectionKey.OP_READ,ByteBuffer.allocate(1024));

        System.out.println(socketChannel.getRemoteAddress()+": 上线");
    }

    private void readData(SelectionKey key) {
        SocketChannel channel = (SocketChannel)key.channel();
        try {

            ByteBuffer byteBuffer = (ByteBuffer)key.attachment();

            int count = channel.read(byteBuffer);
            //读取客户端数据
            if(count>0){
                String msg = new String(byteBuffer.array(),0,count);
                //将缓冲区的数组指向0位置
                byteBuffer.flip();
                //清除缓冲区的数据
                byteBuffer.clear();
                send(msg,channel);

            }

        }catch (Exception e){
            try {
                System.out.println(channel.getRemoteAddress()+": 下线了");
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }

    }

    //给别的客户端发送数据
    private void send(String msg, SocketChannel shelf)throws Exception {
        System.out.println(msg);
        for (SelectionKey key : selector.keys()) {
            SelectableChannel channel = key.channel();
            if(channel instanceof SocketChannel && channel != shelf){
                SocketChannel socketChannel = (SocketChannel)channel;
                ByteBuffer byteBuffer = ByteBuffer.wrap(msg.getBytes());
                socketChannel.write(byteBuffer);
            }
        }
    }


    public static void main(String[] args)throws Exception {
        new ChatServer().listen();
    }
}
